﻿using System;
using System.IO;
using UnityEngine;

#if UNITY_STANDALONE_WIN
using System.Diagnostics;
using System.Reflection;
#endif

using System.Text;
using System.Threading;
using Common;
public class Logger : SingletonMono<Logger>
{
    static private SafeQueue<string> LogBuff = null;
    static private StreamWriter file = null;
    static private Thread PrintThread = null;
    private static bool flag = true;

#if UNITY_EDITOR
    private static bool PrintInUntiyWindow = false;
#endif
    public void Awake()
    {
        if ( !PrintLog )
            return;
        if ( PrintThread != null )
            return;
        if ( !flag )
            return;

        Init();
    }

    private static bool PrintLog
    {
        get
        {
            return true;
        }

    }


    public void Init()
    {
        UnityEngine.Debug.Log("初始化日志打印!!!");
        string path = null;
#if UNITY_EDITOR
        Directory.CreateDirectory("./Log");
        path = "./Log/U3D_OutLog.text";
#elif UNITY_STANDALONE_WIN  
            if (GameListAdapter.isWithHall)
            {
                Directory.CreateDirectory("./Log");
                path = "./Log/U3D_OutLog.text";
            }
            else
            {
                DirectoryInfo dr = new DirectoryInfo(Application.dataPath);
               DirectoryInfo Current=dr.Parent;
                Current.CreateSubdirectory("Log");
               
                path = Current.FullName + "/Log/U3D_OutLog.text";
            }

#elif UNITY_ANDROID
                 path = Application.persistentDataPath + "/U3D_OutLog.txt";
#elif UNITY_IPHONE
			 path = Application.persistentDataPath + "/U3D_OutLog.txt";
#endif

        if ( string.IsNullOrEmpty(path) )
            return;


        //每次启动客户端删除之前保存的Log
        if ( System.IO.File.Exists(path) )
        {
            File.Delete(path);
        }

        file = new StreamWriter(path, true, Encoding.Unicode);
        file.AutoFlush = true;
        //在这里做一个Log的监听
        Application.logMessageReceived += HandleLog;


#if UNITY_IPHONE
        UnityEngine.iOS.Device.SetNoBackupFlag(path);
#endif

        LogBuff = new SafeQueue<string>();

        PrintThread = new Thread(Run);
        PrintThread.IsBackground = true;
        PrintThread.Priority = System.Threading.ThreadPriority.Lowest;
        PrintThread.Start();
    }


    private void HandleLog(string condition, string stackTrace, LogType type)
    {
        LogFile(condition);
        if ( type == LogType.Exception || type == LogType.Error )
        {
            LogFile(stackTrace);
        }
    }



    static private void LogFile(string info)
    {
        if ( file == null )
        {
            return;
        }

        file.WriteLine(info);
        file.Flush();

    }

    public void OnDestroy()
    {

        UnityEngine.Debug.Log("正在销毁 Logger...");
        flag = false;

    }



    private static void LogFile(string info, LogType type)
    {
        switch ( type )
        {
            case LogType.Assert:
                {
                    UnityEngine.Debug.Log(info);
                }
                break;
            case LogType.Log:
                {
                    UnityEngine.Debug.Log(info);
                }
                break;
            case LogType.Warning:
                {
                    UnityEngine.Debug.LogWarning(info);
                }
                break;
            case LogType.Error:
                {
                    UnityEngine.Debug.LogError(info);
                }
                break;
        }
    }


    static private void Run()
    {
        while ( flag )
        {
            if ( LogBuff.Count > 0 )
            {
                string s = LogBuff.Dequeue();
                LogFile(s);
                Thread.Sleep(5);
            }
            else
            {
                Thread.Sleep(30);
            }

        }

        if ( file != null )
        {
            file.Close();
        }

        UnityEngine.Debug.Log("打印线程执行完毕!");
    }


    public static void TraceInfo(string content, string loggerTypeL1 = null, string loggerTypeL2 = null)
    {
        if ( !PrintLog )
            return;
        Logger.OutPutLog(content, loggerTypeL1, loggerTypeL2, true);
    }
    public static void Log(string content, string loggerTypeL1 = null, string loggerTypeL2 = null)
    {
        if ( !PrintLog )
            return;
        Logger.OutPutLog(content, loggerTypeL1, loggerTypeL2, false);
    }
    public static void DebugStackTraceInfo(string content, string loggerTypeL1 = null, string loggerTypeL2 = null)
    {

        if ( !PrintLog )
            return;
        Logger.OutPutLog(content, loggerTypeL1, loggerTypeL2, true);

    }
    public static void WarningInfo(string content, string loggerTypeL1 = null, string loggerTypeL2 = null)
    {
        if ( !PrintLog )
            return;
        OutPutLog(content, loggerTypeL1, loggerTypeL2, false, LogType.Warning);

    }
    public static void LogError(string msg, Type t = null)
    {
        string s = "";
        if ( t != null )
        {
            s = t.ToString();
        }
        ErrorInfo(msg, s);
    }

    public static void LogException(Exception e)
    {
        UnityEngine.Debug.LogException(e);
    }

    public static void ErrorInfo(string content, string loggerTypeL1 = null, string loggerTypeL2 = null)
    {
        if ( !PrintLog )
            return;
        OutPutLog(content, loggerTypeL1, loggerTypeL2, true, LogType.Error);
    }
    public static void DebugInfoCPlusPlus(string content, string loggerTypeL1 = null, string loggerTypeL2 = null)
    {
        if ( !PrintLog )
            return;
        OutPutLog(content, loggerTypeL1, loggerTypeL2, true);
    }


    public static void ErrorInfoCPlusPlus(string content, string loggerTypeL1 = null, string loggerTypeL2 = null)
    {
        if ( !PrintLog )
            return;
        OutPutLog(content, loggerTypeL1, loggerTypeL2, true, LogType.Error);
    }


    private static String GetFuncStackString()
    {

        string text = string.Empty;
#if UNITY_STANDALONE_WIN
        StackTrace stackTrace = new StackTrace(true);
        StackFrame frame = stackTrace.GetFrame(3);
        if (frame != null)
        {
            MethodBase method = frame.GetMethod();
            string text2 = method.DeclaringType.Name + "." + method.Name;
            if (text2 != null)
            {
                string fileName = frame.GetFileName();
                if (fileName != null)
                {
                    int fileLineNumber = frame.GetFileLineNumber();
                    int num = fileName.LastIndexOf("\\");
                    string text3 = fileName.Substring(num + 1);
                    if (text3 != null)
                    {
                        text = string.Concat(new object[]
                        {
                            text,
                            "[func:",
                            text2,
                            "(",
                            text3,
                            ":",
                            fileLineNumber,
                            ")]"
                        });
                    }
                }
            }
        }
#endif
        return text;
    }

    private static void OutPutLog(string msg, string loggerTypeL1 = null, string loggerTypeL2 = null, bool printfFunc = true, LogType logtype = LogType.Log)
    {

        StringBuilder sb = new StringBuilder();
        string time = string.Concat(new object[]
        {
            "[",

            DateTime.Now.Hour,
            ":",
            DateTime.Now.Minute,
            ":",
            DateTime.Now.Second,
            "_",
            DateTime.Now.Millisecond,
            "]"
        });

        sb.Append(time);
        if ( !string.IsNullOrEmpty(loggerTypeL1) )
        {
            sb.Append("[").Append(loggerTypeL1).Append("]");

        }
        if ( !string.IsNullOrEmpty(loggerTypeL2) )
        {
            sb.Append("[").Append(loggerTypeL2).Append("]");
        }

        sb.Append("\t\t");

        sb.Append(msg);

        if ( printfFunc )
        {
            string funcStr = GetFuncStackString();
            sb.Append(funcStr);
        }
#if  UNITY_EDITOR
        if ( LogBuff != null && !PrintInUntiyWindow )
        {
            LogBuff.Enqueue(sb.ToString());
        }
        else
        {
            LogFile(sb.ToString(), logtype);
        }

#else
         LogBuff.Enqueue(sb.ToString());
#endif

        //#if UNITY_STANDALONE_WIN || UNITY_EDITOR
        //        if (Instance != null)
        //        {
        //            Instance.LogFile(sb.ToString());
        //        }
        //        else
        //        {
        //            LogFile(sb.ToString(), logtype);
        //        }
        //#else

        //            LogFile(sb.ToString(),logtype);
        //#endif

    }

}
